package com.rmy.common.utils.ffmpeg;


import com.rmy.common.utils.file.FileUtils;
import jdk.nashorn.internal.objects.Global;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class FfmpegConvertVideo {

    private static String inputPath = "";

    private static String outputPath = "";

    private static String ffmpegPath = "";

    public static void main(String args[]) throws IOException {
//
//        getPath();
//
//        if (!checkfile(inputPath)) {
//            System.out.println(inputPath + " is not file");
//            return;
//        }

        processAVI("E:\\SVN\\product\\ims\\input\\音乐之声-njluyou.rm", "E:\\SVN\\product\\ims\\input\\1.avi");

//        if (process()) {
//            System.out.println("ok");
//        }
    }


    public static boolean convertToMp4(String oldFilePath, String newFilePath) {
        int type = checkContentType(oldFilePath);
        boolean status = false;
        if (type == 0) {
            System.out.println("直接转成mp4格式");
            status = processMp4(oldFilePath, newFilePath);// 直接转成mp4格式
        } else if (type == 1) {
            String tmpFilePath = "";
            try {
                tmpFilePath = File.createTempFile("temp", ".avi").getAbsolutePath();
            } catch (IOException e) {
                e.printStackTrace();
            }
//            String tmpFilePath = Global.getUploadPath() + File.separator + "temp.avi";
            FileUtils.deleteFile(tmpFilePath);
            // 取相对路径
            if (!processAVI(oldFilePath, tmpFilePath)) {
                return false;
            }
            status = processMp4(tmpFilePath, newFilePath);// 将avi转成mp4格式

        }
        return status;
    }

    private static void getPath() { // 先获取当前项目路径，在获得源文件、目标文件、转换器的路径
        File diretory = new File("");
        try {
            String currPath = diretory.getAbsolutePath();
            inputPath = currPath + "\\input\\sea.mov";
            outputPath = currPath + "\\output\\";
            ffmpegPath = currPath + "\\ffmpeg\\";
            System.out.println(currPath);
        }
        catch (Exception e) {
            System.out.println("getPath出错");
        }
    }

//    private static boolean process() {
//        int type = checkContentType(inputPath);
//        boolean status = false;
//        if (type == 0) {
//            System.out.println("直接转成mp4格式");
//            status = processMp4(inputPath);// 直接转成mp4格式
//        } else if (type == 1) {
//            String avifilepath = processAVI(type);
//            if (avifilepath == null)
//                return false;// 没有得到avi格式
//            status = processMp4(avifilepath);// 将avi转成mp4格式
//        }
//        return status;
//    }

    private static int checkContentType(String strFilePath) {
        String type = strFilePath.substring(strFilePath.lastIndexOf(".") + 1, strFilePath.length())
                .toLowerCase();
        // ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
        if (type.equals("avi")) {
            return 0;
        } else if (type.equals("mpg")) {
            return 0;
        } else if (type.equals("wmv")) {
            return 0;
        } else if (type.equals("3gp")) {
            return 0;
        } else if (type.equals("mov")) {
            return 0;
        } else if (type.equals("mp4")) {
            return 0;
        } else if (type.equals("asf")) {
            return 0;
        } else if (type.equals("asx")) {
            return 0;
        } else if (type.equals("flv")) {
            return 0;
        }
        // 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等),
        // 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.
        else if (type.equals("wmv9")) {
            return 1;
        } else if (type.equals("rm")) {
            return 1;
        } else if (type.equals("rmvb")) {
            return 1;
        }
        return 9;
    }

    private static boolean checkfile(String path) {
        File file = new File(path);
        if (!file.isFile()) {
            return false;
        }
        return true;
    }

    // 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等), 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.
    private static boolean processAVI(String oldFilePath, String newFilePath) {
        List<String> commend = new ArrayList<String>();
        commend.add("mencoder");
        commend.add(oldFilePath);
        commend.add("-oac");
        commend.add("lavc");
        commend.add("-lavcopts");
        commend.add("acodec=mp3:abitrate=64");
        commend.add("-ovc");
        commend.add("xvid");
        commend.add("-xvidencopts");
        commend.add("bitrate=600");
        commend.add("-of");
        commend.add("avi");
        commend.add("-o");
        commend.add(newFilePath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            Process process = builder.command(commend).redirectErrorStream(true).start();
            doWaitFor(process);
//            new PrintStream(process.getErrorStream());
//            new PrintStream(process.getInputStream());
//            process.waitFor();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
    private static boolean processFLV(String oldfilepath) {

        if (!checkfile(inputPath)) {
            System.out.println(oldfilepath + " is not file");
            return false;
        }

        List<String> command = new ArrayList<String>();
        command.add(ffmpegPath + "ffmpeg");
        command.add("-i");
        command.add(oldfilepath);
        command.add("-ab");
        command.add("56");
        command.add("-ar");
        command.add("22050");
        command.add("-qscale");
        command.add("8");
        command.add("-r");
        command.add("15");
        command.add("-s");
        command.add("600x500");
        command.add(outputPath + "a.flv");

        try {

            // 方案1
//            Process videoProcess = Runtime.getRuntime().exec(ffmpegPath + "ffmpeg -i " + oldfilepath
//                    + " -ab 56 -ar 22050 -qscale 8 -r 15 -s 600x500 "
//                    + outputPath + "a.flv");

            // 方案2
            Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();

            new PrintStream(videoProcess.getErrorStream()).start();

            new PrintStream(videoProcess.getInputStream()).start();

            videoProcess.waitFor();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private static boolean processMp4(String oldfilepath, String newFilePath) {
        if (!checkfile(oldfilepath)) {
            System.out.println(oldfilepath + " is not file");
            return false;
        }
        List command = new ArrayList();
        command.add("ffmpeg");
        command.add("-i");
        command.add(oldfilepath);
        command.add("-c:v");
        command.add("libx264");
        command.add("-mbd");
        command.add("0");
        command.add("-c:a");
        command.add("aac");
        command.add("-strict");
        command.add("-2");
        command.add("-pix_fmt");
        command.add("yuv420p");
        command.add("-movflags");
        command.add("faststart");
        command.add(newFilePath);//名字
        try {
//            String path=outputPath +"\"+ videoInfo.getVideoContent()+".mp4";
//            String targetFileName1=videoInfo.getVideoContent()+".mp4";
//            videoInfo.setUploadPath(SystemContext.getvideoURL() + targetFileName1);//存放转格式后的路径到数据库
//            String targetFileName = ".mp4"; //文件后缀
//            videoInfo.setVideoSuffix(targetFileName);
// 方案1
// Process videoProcess = Runtime.getRuntime().exec(ffmpegPath + "ffmpeg -i " + oldfilepath
// + " -ab 56 -ar 22050 -qscale 8 -r 15 -s 600x500 "
// + outputPath + "a.flv");
            Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
            new PrintStream(videoProcess.getErrorStream()).start();
            new PrintStream(videoProcess.getInputStream()).start();
            videoProcess.waitFor();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    private static int doWaitFor(Process p) {
        InputStream in = null;
        InputStream err = null;
        int exitValue = -1; // returned to caller when p is finished
        try {
            System.out.println("comeing");
            in = p.getInputStream();
            err = p.getErrorStream();
            boolean finished = false; // Set to true when p is finished

            while (!finished) {
                try {
                    while (in.available() > 0) {
                        Character c = new Character((char) in.read());
                        System.out.print(c);
                    }
                    while (err.available() > 0) {
                        Character c = new Character((char) err.read());
                        System.out.print(c);
                    }

                    exitValue = p.exitValue();
                    finished = true;

                } catch (IllegalThreadStateException e) {
                    Thread.currentThread().sleep(500);
                }
            }
        } catch (Exception e) {
            System.err.println("doWaitFor();: unexpected exception - " + e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }

            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
            if (err != null) {
                try {
                    err.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return exitValue;
    }
}

class PrintStream extends Thread
{
    InputStream __is = null;
    public PrintStream(InputStream is)
    {
        __is = is;
    }

    public void run()
    {
        try
        {
            while(this != null)
            {
                int _ch = __is.read();
                if(_ch != -1)
                    System.out.print((char)_ch);
                else break;
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
